#include "ShaderLibrary.hpp"

std::map<std::string, Shader*> ShaderLibrary::cache;
std::map<std::string, VertexShader*> ShaderLibrary::m_vertexShaders;
std::map<std::string, FragmentShader*> ShaderLibrary::m_fragmentShaders;

void ShaderLibrary::add( Shader* shader, std::string name )
{
	cache[ name ] = shader;
}


Shader* ShaderLibrary::get( std::string name )
{
	return cache[ name ];
}



VertexShader* ShaderLibrary::getVertexShader( std::string filename )
{
	std::map<std::string, VertexShader*>::iterator found = m_vertexShaders.find( filename );
	if( found != m_vertexShaders.end() )
	{
        Logger::write( "ShaderLibrary", "getVertexShader( string )",
                       QString( "\"" ) + filename.c_str() +
                       QString( "\" already loaded" ), Logger::Note );
		return found->second;
	}
	/// @todo Handle unloading/reloading and refrence counting
	
	
	std::string glslFile = loadFile( filename );
	GLuint id = glCreateShader( GL_VERTEX_SHADER ); 

	const char* vp = glslFile.c_str();
	glShaderSource( id, 1, &vp, NULL);
	assert( glGetError() == GL_NO_ERROR);
	
	glCompileShader( id ); 
	assert( glGetError() == GL_NO_ERROR);
	
	VertexShader* shader = new VertexShader( filename, id );
	m_vertexShaders[ filename ] = shader;
	return shader;
}

FragmentShader* ShaderLibrary::getFragmentShader( std::string filename )
{
	std::map<std::string, FragmentShader*>::iterator found = m_fragmentShaders.find( filename );
	if( found != m_fragmentShaders.end() )
	{
        Logger::write( "ShaderLibrary", "getFragmentShader( string )",
                       QString( "\"" ) + filename.c_str() +
                       QString( "\" already loaded" ), Logger::Note );
		return found->second;
	}
	
	/// @todo Handle unloading/reloading and refrence counting
	
	
	std::string glslFile = loadFile( filename );
	GLuint id = glCreateShader( GL_FRAGMENT_SHADER ); 
	
	const char* vp = glslFile.c_str();
	glShaderSource( id, 1, &vp, NULL);
	assert( glGetError() == GL_NO_ERROR);
	
	glCompileShader( id ); 
	assert( glGetError() == GL_NO_ERROR);
	
	FragmentShader* shader = new FragmentShader( filename, id );
	m_fragmentShaders[ filename ] = shader;
	return shader;
}

std::string ShaderLibrary::loadFile( std::string &file )
{
    QFile inFile( file.c_str() );
    if( inFile.open( QFile::ReadOnly | QFile::Text ) ) {
        Logger::write( "ShaderLibrary", "loadFile( string )",
                       QString( "\"" ) + file.c_str() + QString( "\" loading" ),
                       Logger::Note );
        QTextStream in( &inFile );
        return in.readAll().toStdString();
    }
    else {
        Logger::write( "ShaderLibrary", "loadFile( string )",
                       QString( "\"" ) + file.c_str() + QString( "\" not loaded" ),
                       Logger::Error );
        assert( 0 );
    }
}
